var infoBubbleInfo = {
		shadowStyle: 1,
        padding: 20,
        backgroundColor: '#F3F6FA',
        borderRadius: 10,
        arrowSize: 35,
        borderWidth: 1,
        arrowPosition: 30,
        arrowStyle: 2


};
function geoMap()
{
	var map =null;
	var markersCollections = [];
	this.makeMap = function(element,options)
	{
		map = new google.maps.Map(element,options);
		$(element).trigger('onMapSetup',[this]);
	};
	this.getMap = function()
	{
		return map;
	};
	this.addMarker = function(options)
	{
		options.map = this.getMap();
		Marker = new google.maps.Marker(options);
		return Marker;
	};
	this.addEvent = function (obj,event,callback)
	{
		return google.maps.event.addListener(obj,event,callback);
	};
	this.fitBounds = function(markersObject)
	{
		var maxLat = null;
		var minLat = null;
		var maxLng = null;
		var minLng = null;
		for(var i in markersObject)
		{
			var marker = markersObject[i];
			var latLng = marker.getPosition();
			var lat = latLng.lat();
			var lng = latLng.lng();
			if(maxLat == null || lat > maxLat)
			{
				maxLat = lat;
			}
			if(minLat == null || lat < minLat)
			{
				minLat = lat;
			}
			if(maxLng == null || lng > maxLng)
			{
				maxLng = lng;
			}
			if(minLng == null || lng < minLng)
			{
				minLng = lng;
			}
		}
		centerLat = (maxLat+minLat)/2;
		centerLng = (maxLng+minLng)/2;
		var centerLatLng = new google.maps.LatLng(centerLat,centerLng);
		var boundsNELatLng = new google.maps.LatLng(maxLat,maxLng);
		var boundsSwLatLng = new google.maps.LatLng(minLat,minLng);
		var bounds = new google.maps.LatLngBounds(boundsSwLatLng,boundsNELatLng);
		this.getMap().setCenter(centerLatLng);
		var that = this;
		var zoomEvent = this.addEvent(this.getMap(), "bounds_changed", function(){
			google.maps.event.removeListener(zoomEvent);
			if(this.getZoom() > 16)
			{
				this.setZoom(16);
			}
		})
		this.getMap().fitBounds(bounds);
		
	}
}

var GeoAddress = {
		
		getLatLng : function(address)
		{
			
		},
		getAddress : function(lat,lng)
		{
			
		}
};
function GeoMapper()
{
	this.mapObject = null;
	this.markersCollection = [];
	this.defaultMapInitOptions = function(){
		return {
					mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU}
				}
	};
	this.makeMapAndMakers = function(element,mapOptions,markers)
	{
		//don't show map if no markers.
		if(markers.length == 0)
		{
			//return ;
		}
		this.mapObject = new geoMap();
		mapOtions = $.extend(true,mapOptions,this.defaultMapInitOptions(),mapOptions);
		this.mapObject.makeMap(element,mapOptions);
		this.setMarkers(markers);
		this.setCenter();
	};
	this.setMarkers = function(markers)
	{
		for(var i in markers)
		{
			var marker = markers[i];
			this.setMarker(marker);
		}
	};
	this.setMarker = function(marker)
	{
		if(!marker.lat || !marker.lng)
		{
			if(marker.address)
			{
				//@todo address search
				//this.setMarkerAfterAddress(marker);
			}else
			{
				return ;
			}
		}
		var position = new google.maps.LatLng(marker.lat,marker.lng);
		var markerOptions = {position:position};
		if(typeof marker.constructOptions == "object")
		{
			markerOptions = $.extend(markerOptions,marker.constructOptions);
		}
		var markerObject = this.mapObject.addMarker(markerOptions);
		/*if(typeof InfoBubble == "function")
		{
			var bubbleOpts = {content:marker.info};
			bubbleOpts = $.extend(bubbleOpts,infoBubbleInfo);
			var infoWindow = new  InfoBubble(bubbleOpts);
		}else
		{
			var infoWindow = new  google.maps.InfoWindow({content:marker.info,maxWidth:'400px'});
		}*/
                var infoWindow = new  google.maps.InfoWindow({content:marker.info,maxWidth:'400px'});
		this.markersCollection[marker.id] = {markerJson : marker, markerObject : markerObject};
		var mapperObject = this;
		this.mapObject.addEvent(markerObject,'click',function(){
			infoWindow.open(mapperObject.mapObject.getMap(),markerObject);
		});
		//save this click event for some use
		this.markersCollection[marker.id].infoWindow = infoWindow;
	};
	this.setCenter = function()
	{
		var markersObject = new Array;
		for(var i in this.markersCollection)
		{
			//for ingoring empty values.
			if(typeof this.markersCollection[i] != 'object')
			{
				continue;
			}
			markersObject.push(this.markersCollection[i].markerObject);
		}
		if(markersObject.length > 0)
		{
			this.mapObject.fitBounds(markersObject);
		}
	};
	this.getMarker = function(id)
	{
		var marker = null;
		if(typeof this.markersCollection[id] == "object")
		{
			marker = this.markersCollection[id];
		}
		return marker;
	}
}
/**
 * function for on hover event of title
 * @return
 */
GeoMapper.prototype.onTitleHover = function(id,close)
{
	var marker = this.getMarker(id);
	if(!marker)
	{
		return false;
	}
	var infoWindow = marker.infoWindow;
	if(close)
	{
		var fn = "close";
	}else
	{
		var fn = "open";
	}
	this.mapObject.getMap().panTo(marker.markerObject.getPosition());
	infoWindow[fn](this.mapObject.getMap(),marker.markerObject);
}
var Mapper = new GeoMapper();
(function($){
	
	$.fn.fixedDiv = function(options)
	{
		if(this.data('scrollWindowEventAdded'))
		{
			return this;
		}
		var defaultOptions = {fixAfter:null,fixTill:null,classToAdd : 'fixedDiv'};
		var msie6 = typeof $.browser.msie != "undefined" && $.browser.msie == true  && $.browser.version < 7;
		var options = $.extend(defaultOptions,options);
		if (!msie6) {
			var top = 0;
			var bottom = false;
			if(options.fixAfter)
			{
				top = $(options.fixAfter).offset().top - parseFloat($(options.fixAfter).css('margin-top').replace(/auto/, 0));
			}
			if(options.fixTill)
			{
				bottom = $(options.fixTill).offset().top + $(options.fixTill).height() - $(this).height() + parseFloat(this.css('margin-top').replace(/auto/, 0).replace('/px/i',""));
			}
			var element = this;
			var width = this.offset().left;
			this.data('scrollWindowEventAdded',true);
			$(window).scroll(function (event) {
				// what the y position of the scroll is
				var y = $(this).scrollTop();
				// whether that's below the form
				var addClass = false;
				//in %age
				if (y >= top && (bottom == false || y <= bottom)) {
					// if so, ad the fixed class
					addClass = true;
					if(element.data("noFixDiv") === true)
					{
						addClass = false;
					}
					
				} else {
					// otherwise remove it
					
				}
				if(addClass)
				{
					element.addClass(options.classToAdd);
				}else
				{
					element.removeClass(options.classToAdd);
				}
			});
		}
		return this;
	}
})(jQuery)

function makeListingMap(domId,markers,hoverEvent)
{
	Mapper = new GeoMapper();
	var mapData = markers;
	var latLng = {lat:0,lng:0};
	if(latLng)
	{
		var latlng = new google.maps.LatLng( latLng.lat,latLng.lng);
		var mapOptions = {zoom: 1,center:latlng,mapTypeId: google.maps.MapTypeId.ROADMAP};
		Mapper.makeMapAndMakers(document.getElementById(domId),mapOptions,mapData);
	}
	if(hoverEvent)
	{
		$('.listing_title a').mouseover(function(){
			doForLisitingTitleHover($(this).parent(),false);
			}).mouseout(function(){
				doForLisitingTitleHover($(this).parent(),true);
			});
	}
}

function doForLisitingTitleHover(dom,out)
{
	$this = $(dom);
	id = $this.attr('id').split('_').pop();
	Mapper.onTitleHover(id,out);
}

function makeMapForGetDirection(domId, markers, destLat, destLng, allowTravelModeChange)
{
	Mapper = new GeoMapper();
	var mapData = markers;
	var latLng = {lat:0,lng:0};
	var destLatLng = new google.maps.LatLng(destLat, destLng);
	var rendererOptions = {
		draggable: true
	};
	var directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
	var directionsService = new google.maps.DirectionsService();
	
	if(latLng)
	{
		var latlng = new google.maps.LatLng( latLng.lat,latLng.lng);
		var mapOptions = {zoom: 6,center:latlng,mapTypeId: google.maps.MapTypeId.ROADMAP};
		Mapper.makeMapAndMakers(document.getElementById(domId),mapOptions,mapData);
		
		directionsDisplay.setMap(Mapper.mapObject.getMap());
		directionsDisplay.setPanel(document.getElementById('direction_details_div'));

		google.maps.event.addListener(directionsDisplay, 'directions_changed', function() {
		    computeTotalDistance(directionsDisplay.getDirections());
		});
		
		$("#getDirectionsBtn").click(function(){
			calcRoute(destLatLng, directionsDisplay, directionsService);
		});
	}
}

function calcRoute(destLatLng, directionsDisplay, directionsService)
{
	var newTravelMode = google.maps.TravelMode.DRIVING;
	var newSourceAddress = $("#SourceAddress").val();
	var newDestAddress = destLatLng;
	if(!newSourceAddress.length)
	{
		return;
	}
	if(allowTravelModeChange)
	{
		$('#TravelMode').change(function(){
			newTravelMode = $(this).val();
		});
	}
	if($("#SwapPoints").attr('checked'))
	{
		newDestAddress = newSourceAddress;
		newSourceAddress = destLatLng;
	}
	var request = {
		origin: newSourceAddress,
		destination: newDestAddress,
		travelMode: newTravelMode
	};
	directionsService.route(request, function(response, status) {
		if (status == google.maps.DirectionsStatus.OK) {
			directionsDisplay.setDirections(response);
		}
	});
}

function computeTotalDistance(result) {
	var total = 0;
	var myroute = result.routes[0];
	for (var i = 0; i < myroute.legs.length; i++) {
		total += myroute.legs[i].distance.value;
	}
	total = total / 1000.0;
	$('#total_distance_div').val(total + ' km');
}
function locationFinderMap(latField,lngField,locationFields,model,mapDom,defaultlat,defaultLng,popupMessage)
{
  var geocoder;
  var map;
  var marker;
  //var self = this;
  this.setToDefault = function()
  {
      if(defaultLng && defaultlat)
      {
         this.getField(lngField).val(defaultLng);	//.attr("disabled",false)
         this.getField(latField).val(defaultlat);	//.attr("disabled",false)
         this.mapToLatLng(defaultlat, defaultLng, 15);
      }else
      {
          this.mapToLocationValueString("USA",3);
          //this.getField(lngField).attr("disabled",true);
          //this.getField(latField).attr("disabled",true);
      }
  };
  this.resetToCurrentValues = function()
  {
  	google.maps.event.trigger(map, 'resize');
  	 var latLng = {
  	 	lat : this.getField(latField).val(),
  	 	lng : this.getField(lngField).val()
  	 }
  	 if(latLng.lat && latLng.lng)
  	 {
		this.mapToLatLng(latLng.lat,latLng.lng,15);
  	 }else
  	 {
		//this.setToDefault();
  	 }
  }
  
  this.mapToLocationValueString = function(value,zoomTo)
  {
    if(!zoomTo)
    {
	zoomTo = 15;
    }
    if(!geocoder)
    {
      geocoder = new google.maps.Geocoder();
    }
   var self = this;  
   if(value.length)
   {
        geocoder.geocode( {'address': value}, function(results, status) {
              if (status == google.maps.GeocoderStatus.OK) {
              self.mapToLatLng(results[0].geometry.location.lat(),results[0].geometry.location.lng(),zoomTo);
            } else {
                console.log("Geocode was not successful for the following reason: " + status);
            }
        });
    }
  };
  this.mapToLatLng = function(lat,lng,zoomTo)
  {
    var latLng = new google.maps.LatLng(lat,lng);
    var self = this;
    var savePositionCallback = function(marker)
    {
      var pos  = marker.getPosition();
      self.getField(lngField).val(pos.lng());	//.attr("disabled",false)
      self.getField(latField).val(pos.lat());	//.attr("disabled",false)
    }
   if(!zoomTo)
   {
	zoomTo = 15; 
    }
    if(!map)
    {
    	$(mapDom).show();
      	$(mapDom).trigger("onMapCreate");
      map = new google.maps.Map(mapDom[0],{
        center : latLng,
        zoom : zoomTo,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        mapTypeControl: false
      });
      marker = new google.maps.Marker({
        map : map,
        draggable : true,
        position : latLng
      });
      google.maps.event.addListener(marker,'position_changed',function(){
        savePositionCallback(marker);
      });
    }else{
      map.setCenter(latLng);
      marker.setPosition(latLng);
	if(zoomTo){
		map.setZoom(zoomTo);
	}
    }
    if(popupMessage)
    {
       var infoWindow = new google.maps.InfoWindow({content:"<div class='scrollFix'>"+popupMessage+"</div>"});
        infoWindow.open(map,marker);
    }
    //savePositionCallback(marker);
    google.maps.event.trigger(map, "resize");

  };
  this.getField = function(field)
  {
	 return $('[name="data['+model+']['+field+']"]');
  };
  this.getFieldValue = function(field)
  {
    var elem = this.getField(field);
    if(elem.length == 0)
    {
      return "";
    }
    var val;
    if(elem[0].nodeName.toLowerCase() == "select")
     {
       val = elem.children("option").filter(":selected").text();
       if(elem.val().length == 0)
       {
         val = "";
       }
     }else{
       val = elem.val();
     }
     return val;
  }
  if(!defaultLng)
  {
    defaultLng = this.getField(lngField).val();
  }
  if(!defaultlat)
  {
    defaultlat = this.getField(latField).val();
  }
  this.setToDefault();
  var self = this;
  var addFieldChangeListners = function()
  {
    var listner = function()
    {
      var valueArray = [];
      for(var i in locationFields)
      {
        var value = self.getFieldValue(locationFields[i]);
        if(value.length)
        {
          valueArray.push(value);
        }
      }
      if(valueArray.length > 0 || locationFields.length < 2)
      {
          self.mapToLocationValueString(valueArray.join(","));
      }
    }
    for(var i in locationFields)
    {
      self.getField(locationFields[i]).blur(function(){
        listner();
      })
    }
    
    self.getField(latField).blur(function(){
    	self.resetToCurrentValues();
    })
    self.getField(lngField).blur(function(){
    	self.resetToCurrentValues();
    })
    
  }
  addFieldChangeListners();
}